%{
/*
 * Copyright (c) 2000, Red Hat, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by DJ Delorie <dj@cygnus.com>
 * Maintained by Robert Collins <rbtcollins@hotmail.com>
 * Modified by Yospaly, 2008
 *
 */

/* tokenize the setup.ini files.  We parse a string which we've
   previously downloaded.  The program must call ini_init() to specify
   that string. */

#include <wx/wx.h>
#include "inibuilder.h"
#include "iniparse.hpp"

#define YY_INPUT(buf,result,max_size) { result = ini_getchar(buf, max_size); }

static int ini_getchar(char *buf, int max_size);
static void ignore_line (void);

%}

/*%option debug */
%option noyywrap
%option yylineno
%option never-interactive

STR    [!a-zA-Z0-9_./:\+-]+

%%

[0123456789abcdef]{32,32}       {
    yylval = (char *) new char[16];
    
    for (int i=0; i< 16; ++i)
        yylval [i] = 0;
    
    for (int i=0; i< 32; ++i) {
        char val = (char) yytext[i];
        if (val > '9')
            val = val - 'a' + 10;
        else
          val = val - '0';
        
        yylval[i / 2] += val << ((i % 2) ? 0 : 4);
    }
    
    return MD5;
}

\"[^"]*\"        { yylval = new char [strlen (yytext+1) + 1];
              strcpy (yylval, yytext+1);
              yylval[strlen (yylval)-1] = 0;
              return STRING; }

"setup-timestamp:"    return SETUP_TIMESTAMP;
"setup-version:"    return SETUP_VERSION;
"Package:"        return PACKAGENAME;
[vV]"ersion:"        return PACKAGEVERSION;
"install:"|"Filename:"    return INSTALL;
"source:"        return SOURCE;
"sdesc:"        return SDESC;
"ldesc:"        return LDESC;
"message:"		return MESSAGE;

"category:"|"Section:"    return CATEGORY;
"requires:"        return REQUIRES;

^{STR}":"        ignore_line ();

"[curr]"        return T_CURR;
"[test]"        return T_TEST;
"[exp]"         return T_TEST;
"[prev]"        return T_PREV;

"@"            return AT;

{STR}            { yylval = new char [strlen(yytext) + 1];
                strcpy (yylval, yytext);
              return STRING; }

[ \t\r]+        /* do nothing */;

^"#".*\n        /* do nothing */;

\n            { return NL; }
.            { return *yytext;}

%%

static wxInputStream* stream = NULL;
extern IniBuilder *iniBuilder;
wxString current_ini_name, yyerror_messages;
int yyerror_count;

void ini_init(wxInputStream& is, IniBuilder& inibuilder) {
  stream = &is;
  iniBuilder = &inibuilder;
  YY_FLUSH_BUFFER;
  yylineno = 1;
  yyerror_count = 0;
  yyerror_messages.Clear ();
}

static int ini_getchar(char *buf, int max_size) {
    static ssize_t readed_len = 0;
    
    if (stream) {
        ssize_t len = stream->Read(buf, max_size).LastRead();
        
        if (len < 1) {
            len = 0;
            stream = NULL;
        }
        return len;
    }
    
    return 0;
}

static void ignore_line () {
    char c;
    while ((c = yyinput ())) {
        if (c == EOF)
            return;
        if (c == '\n')
            return;
    }
}

int yyerror (const char* str) {
    const wxString& s = wxString::FromAscii(str);

    wxString tmp = wxString::Format(_T("%d"), yylineno - (!!YY_AT_BOL ()));
    
    wxString e = current_ini_name + _(" line ") + tmp + _(": ") + s;

    if (!yyerror_messages.IsEmpty())
        yyerror_messages.Append(_("\n"));

    yyerror_messages += e;
    // OutputDebugString (e.c_str ());
    yyerror_count++;
    /* TODO: is return 0 correct? */
    return 0;
}

